﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;

namespace DisplayBoardInfoClient
{
    /// <summary>
    /// Klasa przechowująca uporządkowaną listę wizyt danego pokoju w danym dniu. Udostępnia je na potrzeby wyświetlania odpowiednich danych.
    /// Zbudowana zgodnie z wzorcem Singleton
    /// </summary>
    class DailyPlan
    {
        /// <summary>
        /// Uporządkowana względem czasu lista wizyt.
        /// </summary>
        private static SortedList<Int32,PatientVisit> dayPlan=new SortedList<Int32,PatientVisit>();

        private static SortedList<Int32, DayOpenList> weekOpeningHours = new SortedList<int,DayOpenList>();
        /// <summary>
        /// Obiekt wykozystywany do uzyskania zamka podczas tworzenia instancji klasy.
        /// </summary>
        private static object syncRoot = new Object();
        /// <summary>
        /// Instancja klasy tworzona zgodnie ze wzorcem Singleton.
        /// </summary>
        private static volatile DailyPlan instance;
        /// <summary>
        /// Pierwowzór wprowadzania opóźnienia.
        /// </summary>
        [Obsolete("Delay is automatically corrected by server.")]
        TimeSpan dalay = new TimeSpan(0);
        [Obsolete("Delay is automatically corrected by server.")]
        public void delay(TimeSpan time)
        {
            dalay.Add(time);
            foreach (PatientVisit patient in dayPlan.Values)
            {
                patient.delay(time);
            }
        }
        /// <summary>
        /// Pozwala na pobranie instancji klasy.
        /// </summary>
        public static DailyPlan Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new DailyPlan();
                    }
                }

                return instance;
            }
        }
        /// <summary>
        /// Tworzy listę wizyt na podstawie odpowiedzi uzyskanej od serwera. Lista jest porządkowana pod względem godziny przyjęcia.
        /// </summary>
        /// <param name="xmlResponse"></param>
        public static void init(string xmlResponse)
        {
            dayPlan.Clear();
            XmlDocument document = new XmlDocument();
            document.LoadXml(xmlResponse);
            XmlNodeList lista = document.GetElementsByTagName("visit");
            SortedList<int, PatientVisit> listtemp = new SortedList<int, PatientVisit>();
            foreach (XmlElement el in lista)
            {
                XmlElement pat=(XmlElement)el.GetElementsByTagName("patient")[0];
                string datetext=el.GetElementsByTagName("date")[0].InnerText;
                DateTime date = new DateTime(Int32.Parse(datetext.Substring(0,4)),
                    Int32.Parse(datetext.Substring(5,2)),Int32.Parse(datetext.Substring(8,2)),
                    Int32.Parse(datetext.Substring(11,2)),Int32.Parse(datetext.Substring(14,2)),
                    Int32.Parse(datetext.Substring(17,2)));
                int duration=Int32.Parse(el.GetElementsByTagName("duration")[0].InnerText.Substring(14,2));
                int keyint = date.Hour * 100 + date.Minute;
                while (listtemp.ContainsKey(keyint))
                {
                    keyint++;
                }
                listtemp.Add(keyint, new PatientVisit(date, ((XmlElement)pat).GetElementsByTagName("surname")[0].InnerText,
                    ((XmlElement)pat).GetElementsByTagName("name")[0].InnerText,
                    ((XmlElement)pat).GetElementsByTagName("pesel")[0].InnerText,
                    duration, ((XmlElement)pat).GetElementsByTagName("id")[0].InnerText, ((XmlElement)el).GetElementsByTagName("id")[0].InnerText));

            }
            int i = 0;
            foreach (int key in listtemp.Keys)
            {
                dayPlan.Add(i, listtemp[key]);
                i++;
            }
        }
        public static void openingHours(string xmlResponse){
            weekOpeningHours.Clear();
            XmlDocument document = new XmlDocument();
            document.LoadXml(xmlResponse);
            XmlNodeList lista = document.GetElementsByTagName("admission");
            SortedList<int, PatientVisit> listtemp = new SortedList<int, PatientVisit>();
            for (int i = 0; i < 7; i++)
            {
                weekOpeningHours.Add(i, new DayOpenList());
            }
            foreach (XmlElement el in lista)
            {
                weekOpeningHours[Int32.Parse(el.GetElementsByTagName("dayOfWeek")[0].InnerText)].addAdmission(el);

            }
        }
        /// <summary>
        /// Pozwala na pobranie wizyty z danego miejsca w kolejności. Kolejność wyznaczana godziną przyjęcia.
        /// </summary>
        /// <param name="i">numer wizyty w kolejce począwszy od 0</param>
        /// <returns>obiekt wyzyty lub null jeżeli nie ma wizyty na danym miejscu</returns>
        public PatientVisit get(int i)
        {
            if (dayPlan.ContainsKey(i))
            {
                return dayPlan[i];
            }
            else
            {
                return null;
            }
        }
        public DayOpenList getAdmission(DayOfWeek day)
        {
            switch (day)
            {
                case DayOfWeek.Sunday:
                    {
                        return weekOpeningHours[0];
                    }
                case DayOfWeek.Monday:
                    {
                        return weekOpeningHours[1];
                    }
                case DayOfWeek.Tuesday:
                    {
                        return weekOpeningHours[2];
                    }
                case DayOfWeek.Wednesday:
                    {
                        return weekOpeningHours[3];
                    }
                case DayOfWeek.Thursday:
                    {
                        return weekOpeningHours[4];
                    }
                case DayOfWeek.Friday:
                    {
                        return weekOpeningHours[5];
                    }
                case DayOfWeek.Saturday:
                    {
                        return weekOpeningHours[6];
                    }

            }
            return null;
        }
    }
}
